package game.targets.entity.world;

import game.targets.entity.Entity;
import game.targets.entity.world.arrow.Arrow;
import game.targets.observer.Subject;
import game.targets.room.Room;

import java.util.Vector;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.utils.AnimationController;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Vector3;

public class Bow extends Entity {
	private Arrow arrow;
	private ArrowStatic arrowStatic;
	private AnimationController controller;
	private float animSpeed;
	private PerspectiveCamera camera;

	public Bow(Vector3 pos, PerspectiveCamera camera, Subject subject) {
		super(pos, new Vector3(1, 0, 0), BOW_MODEL, subject);
		controller = new AnimationController(graphics.getInstance());
		// this.setScale(0.5f, 0.5f, 0.01f);
		animSpeed = 1;
		arrowStatic = new ArrowStatic(new Vector3(this.getPosition()), subject);
		this.camera = camera;
	}

	public void resetStaticArrow() {
		arrowStatic.setPosition(this.getPosition());

	}

	public void createArrow(float angleZ, float angleY) {
		arrow = new Arrow(new Vector3(arrowStatic.getPosition()), subject);
		arrow.rotate(Vector3.Y, angleZ);
		arrow.rotate(Vector3.Z, -angleY);

	}

	public void rotate(Vector3 axis, float angle) {
		graphics.rotate(axis, angle);
		float rad = angle * MathUtils.degreesToRadians;
		Vector3 tmp1 = new Vector3(direction);
		Vector3 tmp2 = new Vector3(axis);
		Vector3 tmp3 = new Vector3(axis);
		tmp1 = tmp1.scl(MathUtils.cos(rad));
		tmp2 = tmp2.crs(direction).scl(MathUtils.sin(rad));
		float dot = tmp3.dot(direction) * (1 - MathUtils.cos(rad));
		tmp3.scl(dot);
		direction = tmp1.add(tmp2).add(tmp3);
	}

	@Override
	public void update(float delta) {
		arrowStatic.update(delta);
		controller.update(animSpeed * Gdx.graphics.getDeltaTime());
		// graphics.getInstance().transform=camera.combined;
	}

	@Override
	public void render(ModelBatch batch, Environment environment) {
		super.render(batch, environment);
		arrowStatic.render(batch, environment);
	}

	public void fireArrow(Vector3 targetPos, float charge) {
		// get arrow rotation left or right
		float angleZ = MathUtils.atan2(targetPos.z, -Room.DISTANCE_TO_TARGET_WALL) * MathUtils.radiansToDegrees;
		float angleY = MathUtils.atan2(targetPos.y, -Room.DISTANCE_TO_TARGET_WALL) * MathUtils.radiansToDegrees;
		createArrow(angleZ, angleY);
		arrowStatic.fire();
		Vector3 tmp = new Vector3(targetPos.sub(arrow.getPosition()));
		arrow.fire(tmp, charge);
		// cancel the animation
		controller.setAnimation(null);
		resetStaticArrow();
	}

	public Arrow getArrow() {
		return arrow;
	}

	public void setArrow(Arrow arrow) {
		this.arrow = arrow;
	}

	public void charge(Vector3 dir) {
		animSpeed = 1;
		controller.setAnimation(null);
		controller.setAnimation("Default Take", 1);
		resetStaticArrow();
		arrowStatic.charge(this.direction);
	}

	public void hold() {
		animSpeed = 0;
		arrowStatic.hold();
	}

	public ArrowStatic getStaticArrow() {
		return arrowStatic;
	}

	public void setArrowStatic(ArrowStatic arrowStatic) {
		this.arrowStatic = arrowStatic;
	}

}
